﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;

namespace TestCluster.usermodels
{
    /// <summary>
    /// 用户信息
    ///</summary>
    [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "add" })]
    public class UserInfoAppService : IUserAppService
    {

        //private readonly IRepository<UserInfo, int> _repository;

        private readonly ITestClusterDbContext _dbContext;

        private readonly ModelHelper _modelHelper;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="modelHelper"></param>
        /// <param name="dbcontext"></param>
        /// <param name="accers"></param>
        public UserInfoAppService(ModelHelper modelHelper, ITestClusterDbContext dbcontext, IHttpContextAccessor accers) : base(accers)
        {
            _dbContext = dbcontext;
            _modelHelper = modelHelper;
        }


        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="dbcontext"></param>
        //public UserInfoAppService(ITestClusterDbContext dbcontext)
        //{
        //    _dbContext = dbcontext;
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="page"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<PagedResultDto<UserInfoListDto>> GetListAsync(int page = 1, int size = 20)
        {

            var query = _dbContext.UserInfo.Where(t => 1 == 1).OrderBy(xy => xy.Id);

            var pagedResultDto = new PagedResultDto<UserInfoListDto>();
            pagedResultDto.TotalCount = await query.CountAsync();
            var userList = await query.Page(page, size).AsNoTracking().ToListAsync();
            var temList = ObjectMapper.Map<List<UserInfo>, List<UserInfoListDto>>(userList);

            var uids = temList.Select(t => t.Id).ToList();
            if (uids.Any())
            {
                var querybind = await (from a in _dbContext.BindUserPart.Where(x => uids.Contains(x.UserId))
                                       join b in _dbContext.PartInfo on a.PartId equals b.Id into c
                                       from d in c.DefaultIfEmpty()
                                       select new PartInfoListDto
                                       {
                                           UserId = a.UserId,
                                           Id = d.Id,
                                           Name = d.Name
                                       }).ToListAsync();

                foreach (var item in temList)
                {
                    item.Parts = querybind.Where(x => x.UserId == item.Id).ToList();
                }
            }

            pagedResultDto.Items = temList;
            return pagedResultDto;
        }

        /// <summary>
        /// 根据ID获取单项用户信息
        ///</summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public UserInfoDto GetByIdAsync(int id)
        {
            var query = _dbContext.UserInfo.Where(t => t.Id == id)
                .FirstOrDefault();
            var temList = ObjectMapper.Map<UserInfo, UserInfoDto>(query);
            return temList;
        }

        /// <summary>
        /// 根据ID获取待更新单项信息用户信息
        ///</summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<UserInfoDto> GetInfoForUpdateAsync(int id)
        {
            var query = _dbContext.UserInfo.Where(t => t.Id == id).AsNoTracking().FirstOrDefault();
            var temList = ObjectMapper.Map<UserInfo, UserInfoDto>(query);

            temList.Parts = await ReadUserParts(id);

            return temList;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="userid"></param>
        /// <returns></returns>
        private async Task<List<PartInfoListDto>> ReadUserParts(int userid)
        {
            var querybind = await (from a in _dbContext.BindUserPart.Where(x => x.UserId == userid)
                                   join b in _dbContext.PartInfo on a.PartId equals b.Id into c
                                   from d in c.DefaultIfEmpty()
                                   select new PartInfoListDto
                                   {
                                       UserId = a.UserId,
                                       Id = d.Id,
                                       Name = d.Name
                                   }).ToListAsync();
            return querybind;
        }

        /// <summary>
        /// 添加一个用户信息
        ///</summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<UserInfoDto> CreateItemAsync(UserInfoAddDto input)
        {
            var find = _dbContext.UserInfo.Where(x => x.Email == input.Email).Any();
            if (find)
            {
                throw new TestClusterException("登录邮箱重复，无法继续添加，请确认！");
            }

            var newu = ObjectMapper.Map<UserInfoAddDto, UserInfo>(input);
            newu.CreateDate = DateTime.Now;
            newu.IsEnable = true;//添加自定义
            newu.PassWord = input.PassWord.ToMd5Lower();
            //var updated = await _repository.InsertAsync(newu, true);
            if (!String.IsNullOrWhiteSpace(input.Grade))
            {
                var grade = _dbContext.GradeInfo.Where(x => x.Name == input.Grade).FirstOrDefault();
                if (grade != null && grade != default)
                {
                    newu.GradeId = grade.Id;
                }
                else
                {
                    newu.Grade = "";
                }
            }
            _dbContext.Add(newu);
            await _dbContext.SaveChangesAsync();

            if (input.partids != null && input.partids.Any())
            {
                var parts = _dbContext.PartInfo.Where(x => input.partids.Contains(x.Id)).AsNoTracking().Select(x => x.Id).ToList();
                if (parts.Any())
                {
                    foreach (var item in parts)
                    {
                        var one = new BindUserPart();
                        one.PartId = item;
                        one.UserId = newu.Id;
                        _dbContext.Add(one);
                    }
                    await _dbContext.SaveChangesAsync();
                }
            }

            var backinfo = ObjectMapper.Map<UserInfo, UserInfoDto>(newu);
            backinfo.Parts = await ReadUserParts(newu.Id);

            return backinfo;
        }
        /// <summary>
        /// 更新一个用户信息
        ///</summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<UserInfoDto> UpdateItemAsync(UserInfoUpdateDto input)
        {
            var info = await _dbContext.UserInfo.Where(x => x.Id == input.Id).FirstOrDefaultAsync();
            if (info == null || info == default)
            {
                throw new TestClusterException("需要查询的信息不存在", "404");
            }
            var oldpass = info.PassWord;
            ObjectMapper.Map<UserInfoUpdateDto, UserInfo>(input, info);
            if (!String.IsNullOrEmpty(input.PassWord))
            {
                info.PassWord = input.PassWord.ToMd5Lower();
            }
            else
            {
                info.PassWord = oldpass;
            }
            if (input.partids != null && input.partids.Any())
            {
                var parts = _dbContext.PartInfo.Where(x => input.partids.Contains(x.Id)).AsNoTracking().Select(x => x.Id).ToList();
                if (parts.Any())
                {
                    //当前拥有的关系
                    var haveids = _dbContext.BindUserPart.Where(x => x.UserId == info.Id).Select(x => x.PartId).ToList();
                    //需要删除的关系
                    var dellist = haveids.Except(parts).ToList();
                    if (dellist.Any())
                    {
                        var dels = _dbContext.BindUserPart.Where(x => x.UserId == info.Id && dellist.Contains(x.PartId)).ToList();
                        if (dels.Any())
                        {
                            _dbContext.RemoveRange(dels);
                        }
                    }
                    //需要新增的关系
                    var addlist = parts.Except(haveids).ToList();
                    if (addlist.Any())
                    {
                        foreach (var item in addlist)
                        {
                            var one = new BindUserPart();
                            one.PartId = item;
                            one.UserId = info.Id;
                            _dbContext.Add(one);
                        }
                    }
                }
            }
            else
            {
                //移除所有的
                var bind = _dbContext.BindUserPart.Where(x => x.UserId == info.Id).ToList();
                if (bind.Any())
                {
                    _dbContext.RemoveRange(bind);
                }
            }
            if (!String.IsNullOrWhiteSpace(input.Grade))
            {
                var grade = _dbContext.GradeInfo.Where(x => x.Name == input.Grade).FirstOrDefault();
                if (grade != null && grade != default)
                {
                    info.GradeId = grade.Id;
                }
                else
                {
                    info.Grade = "";
                }
            }
            await _dbContext.SaveChangesAsync();
            var backinfo = ObjectMapper.Map<UserInfo, UserInfoDto>(info);
            backinfo.Parts = await ReadUserParts(info.Id);
            return backinfo;
        }


        /// <summary>
        /// 获取自己级下级账号列表
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<List<UserInfoListDto>> ReadMyChilrenList()
        {
            return await _modelHelper.ReadMyAndNextUserList(_dbContext, base.ReadCurrentUserId());

        }


    }
}
